package com.ll19.dao.jpa;

import java.util.List;

import javax.persistence.Query;
import javax.persistence.Table;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.ll19.dao.UserDao;
import com.ll19.model.User;

/**
 * This class interacts with Spring's HibernateTemplate to save/delete and
 * retrieve User objects.
 * 
 * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a> Modified by
 *         <a href="mailto:dan@getrolling.com">Dan Kibler</a> Extended to
 *         implement Acegi UserDetailsService interface by David Carter
 *         david@carter.net Modified by <a href="mailto:bwnoll@gmail.com">Bryan
 *         Noll</a> to work with the new BaseDaoHibernate implementation that
 *         uses generics.
 */
@Repository("userDao")
public class UserDaoJpa extends GenericDaoJpa<User, Long> implements UserDao,
		UserDetailsService {
	@Autowired
	private DataSource dataSource;

	/**
	 * Constructor that sets the entity to User.class.
	 */
	public UserDaoJpa() {
		super(User.class);
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("unchecked")
	public List<User> getUsers() {
		Query q = getEntityManager().createQuery(
				"select u from User u order by upper(u.username)");
		return q.getResultList();
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("unchecked")
	@Transactional
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException {
		Query q = getEntityManager().createQuery(
				"select u from User u where username=?");
		q.setParameter(1, username);
		List<User> users = q.getResultList();
		if (users == null || users.isEmpty()) {
			throw new UsernameNotFoundException("user '" + username
					+ "' not found...");
		} else {
			return users.get(0);
		}
	}

	/**
	 * Save user and flush entityManager
	 * 
	 * @param user
	 *            the user to save
	 * @return the updated user
	 */
	public User saveUser(User user) {
		User u = super.save(user);
		// flush 与数据库同步数据 但不会提交事务
		// 在某些情况下 比如你需要先插入然后查询统计 则需要 flush
		// 否则hibernate会在最后统一执行SQL的批处理 查询出来的数据很可能不准确
		getEntityManager().flush();
		return u;
	}

	/**
	 * {@inheritDoc}
	 */
	public String getUserPassword(Long userId) {
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
		// 找到User中的table注释并得到注释的信息 比如 name 或者 table.schema()
		// User中注释了@Table(name = "app_user") AnnotationUtils.findAnnotation
		// 可以尝试帮你找到这个注释信息 如果没有会返回NULL
		Table table = AnnotationUtils.findAnnotation(User.class, Table.class);

		return jdbcTemplate.queryForObject(
				"select password from " + table.name() + " where id=?",
				String.class, userId);
	}
}
